package com.rpc.demo.consumer.proxy;

import com.rpc.demo.common.zookeeper.ServiceSubscribe;

import com.rpc.demo.consumer.handler.NettyClientHandler;
import com.rpc.demo.consumer.server.ConsumerNettyServer;

import java.lang.reflect.Proxy;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Author: ZhaoJie
 * @Date: 2022/3/29
 * @Description :
 * @Modify :
 * ===================================================
 * Modifier        Modifytime        Description
 * ===================================================
 */
public class ConsumerProxy {

    /**
     *  注册中心service
     */
    public ConsumerProxy(ServiceSubscribe serviceSubscribe) {
        this.serviceSubscribe = serviceSubscribe;
    }

    /**
     *
     */
    public static ConsumerNettyServer consumerNettyServer;

    private ServiceSubscribe serviceSubscribe;

    //创建线程池
    private static ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

    private static NettyClientHandler client;
    private int count = 0;

    //编写方法使用代理模式，获取一个代理对象

    public Object getBean(final Class<?> serivceClass, final String providerName) {
        // 返回代理对象，同时通过创建新线程的方法得到返回结果
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                new Class<?>[]{serivceClass}, (proxy, method, args) -> {
                    /* 这里实际上就是实现了 InvocationHandler 接口，远程调用代理的是接口，不是具体的实现类，所以就没有用到  proxy(代理对象)
                    以及method(代理对象的实现方法)，只使用到了参数信息args
                    */
                    //在注册中心订阅服务, 返回对应的服务url
                    String rpcHost = serviceSubscribe.subscribe(providerName);
                    String[] split = rpcHost.split(":");
                    System.out.println("(proxy, method, args) 进入...." + (++count) + " 次");

                    // 创建新的consumer netty 服务器
                    if (client == null) {
                        client = new NettyClientHandler();
                        consumerNettyServer = new ConsumerNettyServer(split[0], Integer.parseInt(split[1]), client);
                    }

                    //设置要发给服务器端的调用参数信息
                    client.setPara(args, serivceClass.getName(), method.getName(), method.getParameterTypes());

                    //返回结果
                    return executor.submit(client).get();

                });
    }
}

